home *** CD-ROM | disk | FTP | other *** search
/ Scene Storm / Scene Storm - Volume 1.iso / coding / c / filezap / filezap.c < prev    next >
C/C++ Source or Header  |  1996-01-19  |  12KB  |  402 lines

  1. #include "ram:filezap/filezap_protos.h"
  2.  
  3. /* FileZAP.c : (c) 1986 John Hodgson
  4.    
  5.    FileZAP provides a disk-based file zap utility as popularized
  6.    on TRS systems. Although tested, the author cannot be held liable
  7.    for incidental or consequential damage incurred through the use
  8.    of this program.
  9.  
  10.    Special attention was paid to correct and proper EOF handling;
  11.    please notify the author of any discrepancies (cursor movement
  12.    errors, file growth and/or shrinkage)
  13.  
  14.    Note : Although the physical length of Amiga sectors is just short
  15.    of 512 bytes, 256 byte records are the longest ones that can be
  16.    displayed nicely on a 80x24 screen with all pertinent information.
  17.  
  18.    Have fun! Let's help make this world free from protected disks!
  19.  
  20.    John Hodgson
  21.    P.O. Box 1643
  22.    Pebble Beach, Ca. 93953
  23.  
  24.    Rev 2.2 : Certain portability problems resolved for Aztec "C"
  25. */
  26.  
  27. #define AZTEC /* Omit if Lattice */
  28.  
  29. #ifdef AZTEC 
  30.   #include <ctype.h> /* not in lib like Lattice */
  31.   #include <fcntl.h>
  32. #else /* Lattice? */
  33.   #include <lattice/fcntl.h>
  34. #endif
  35.  
  36. #include <exec/types.h>
  37. #include <intuition/intuition.h>
  38.  
  39. #define CR 13
  40. #define EOF 0
  41. #define ERROR -1
  42. #define HEX 0
  43. #define ASC 1
  44.  
  45. #define IREV 29L /* Intuition rev */
  46. struct IntuitionBase *IntuitionBase;
  47.  
  48. /* record buffer physical cursor position (0-15 rows x 0-15 cols) */
  49. int phycurx=0,phycury=0;
  50.  
  51. /* physical x-position to video x-cursor map table */
  52. int posconv[16]={ 6,8,10,12,15,17,19,21,24,26,28,30,33,35,37,39 };
  53.  
  54. main(argc,argv)
  55. int argc;
  56. char *argv[];
  57. {
  58.   unsigned char inkey,prevchar,secbuf[256],strbuf[80],hexbuf[2];
  59.   int rdfp,wtfp,status,lastrec,curec,shiftnum,len,eof,col;
  60.   long lseek();
  61.   struct IntuitionBase *OpenLibrary();
  62.  
  63.   IntuitionBase=OpenLibrary("intuition.library",IREV);
  64.   if (IntuitionBase==NULL) { 
  65.     printf("Error opening Intuition. Exiting...\n");
  66.     exit(0); /* used by DisplayBeep() */
  67.   }
  68.  
  69.   if (argc!=2) { printf("Usage : filezap file\n"); exit(0); }
  70.   if ((rdfp=open(argv[1],O_RDWR))==ERROR) {
  71.     printf("Error opening file %s. Exiting...\n",argv[1]);
  72.     exit(0);
  73.   }
  74.    
  75.   if ((wtfp=open("raw:0/0/640/200/FileZap 2.2 (c) 1986 John Hodgson",O_RDWR))
  76.        ==ERROR) {
  77.     printf("Error opening window. Exiting...\n");
  78.     close(rdfp,&secbuf[0]);
  79.     exit(0);
  80.   }
  81.   
  82.   curec=1; shiftnum=0;
  83.   lastrec=(lseek(rdfp,-1L,2)/256)+1; /* compute last record #, 1..n */
  84.  
  85.   /* compute EOF remainder by reading from last record */ 
  86.   lseek(rdfp,(long)((lastrec-1)*256),0); eof=read(rdfp,&secbuf[0],256);
  87.  
  88.   /* All data gathered, read 1st record */
  89.   lseek(rdfp,0L,0); status=read(rdfp,&secbuf[0],256);
  90.  
  91.   for (col=0;col<=0xf0;col+=0x10) {
  92.     hexconv(&hexbuf[0],col);
  93.     write(wtfp,&hexbuf[0],2);
  94.     write(wtfp," : \n",4);
  95.   }
  96.   
  97.   prstr(wtfp,62,4,"File : "); write(wtfp,argv[1],strlen(argv[1]));
  98.  
  99.   len=sprintf(&strbuf[0],"EOF : %d",eof);
  100.   prstr(wtfp,62,5,&strbuf[0]);
  101.  
  102.   prstr(wtfp,62,4,"File : "); write(wtfp,argv[1],strlen(argv[1]));
  103.   prstr(wtfp,8,18,"COMMANDS : S) Starting record      E) Ending record");
  104.   prstr(wtfp,8,19,"           F) Forward record       B) Backward record");
  105.   prstr(wtfp,8,20,"           U) Update record        R) Recover record");
  106.   prstr(wtfp,8,21,"      <SPACE> : enter HEX modify   * : enter ASCII modify");
  107.   prstr(wtfp,8,23,"          <n>CR : goto record n    ^C : exit program");
  108.  
  109.   display_record(wtfp,&secbuf[0],curec,lastrec,status);
  110.   movecur(wtfp,&secbuf[0],0,0,status); /* display initial cursor */
  111.   prevchar='\0'; /* zero previous char (used for escape checks) */
  112.  
  113.   do {
  114.     read(wtfp,&inkey,1); /* synchronous kybd scan */
  115.  
  116.     if (prevchar==0x9b) { /* Give 2-byte CSI sequences priority (arrows) */
  117.       prevchar='\0';
  118.       switch(inkey) {
  119.         case 'A':
  120.           movecur(wtfp,&secbuf[0],0,-1,status);
  121.           break;
  122.         case 'B':
  123.           movecur(wtfp,&secbuf[0],0,1,status);
  124.           break;
  125.         case 'C':
  126.           movecur(wtfp,&secbuf[0],1,0,status);
  127.           break;
  128.         case 'D':
  129.           movecur(wtfp,&secbuf[0],-1,0,status);
  130.           break;
  131.       }
  132.       continue; /* no point in further tests, restart */
  133.     }
  134.  
  135.     inkey=toupper(inkey); /* force UC for testing */
  136.        
  137.     /* "Goto" record handling - buffer all digits into a shift
  138.        register until too large, or non-digit pressed */
  139.  
  140.    if (isdigit(inkey)) shiftnum=shiftnum*10+inkey-'0';
  141.     else
  142.       if (inkey!=CR) shiftnum=0;
  143.     if (shiftnum>lastrec) shiftnum=0;
  144.  
  145.     if ((inkey==13) && (shiftnum>0)) { /* Goto */
  146.       lseek(rdfp,(long)(256*(shiftnum-1)),0);
  147.       status=read(rdfp,&secbuf[0],256);
  148.       curec=shiftnum; shiftnum=0;
  149.       display_record(wtfp,&secbuf[0],curec,lastrec,status);
  150.       phycurx=phycury=0; movecur(wtfp,&secbuf[0],0,0,status);
  151.     }
  152.       
  153.     if ((inkey=='F') && (curec<lastrec)) { /* Forward record */
  154.       status=read(rdfp,&secbuf[0],256);
  155.       ++curec;
  156.       display_record(wtfp,&secbuf[0],curec,lastrec,status);
  157.       phycurx=phycury=0;movecur(wtfp,&secbuf[0],0,0,status);
  158.     }
  159.     if ((inkey=='B') && (curec>1)) { /* Backward record */
  160.       --curec;
  161.       lseek(rdfp,(long)((curec-1)*256),0);
  162.       status=read(rdfp,&secbuf[0],256);
  163.       display_record(wtfp,&secbuf[0],curec,lastrec,status);
  164.       phycurx=phycury=0;movecur(wtfp,&secbuf[0],0,0,status);
  165.     }
  166.     switch(inkey) { 
  167.       case 'R': /* Restore (unmodified) record */
  168.         lseek(rdfp,(long)((curec-1)*256),0);
  169.         status=read(rdfp,&secbuf[0],256);
  170.         display_record(wtfp,&secbuf[0],curec,lastrec,status);
  171.         phycurx=phycury=0;movecur(wtfp,&secbuf[0],0,0,status);
  172.         break;
  173.       case 'S': /* Rewind */
  174.         curec=1;
  175.         lseek(rdfp,0L,0);
  176.         status=read(rdfp,&secbuf[0],256);
  177.         display_record(wtfp,&secbuf[0],curec,lastrec,status);
  178.         phycurx=phycury=0;movecur(wtfp,&secbuf[0],0,0,eof);
  179.         break;
  180.       case 'U': /* Update (save modified) record */
  181.         lseek(rdfp,(long)-status,1);
  182.         write(rdfp,&secbuf[0],status);
  183.         DisplayBeep(NULL);
  184.         break;
  185.       case 'E': /* skip to Ending record */
  186.         curec=lastrec;
  187.         lseek(rdfp,(long)(curec-1)*256,0);
  188.         status=read(rdfp,&secbuf[0],256);
  189.         display_record(wtfp,&secbuf[0],curec,lastrec,status);
  190.         phycurx=phycury=0;movecur(wtfp,&secbuf[0],0,0,status);
  191.         break;
  192.       case ' ': /* Enter hex-modify mode */
  193.         edit_window(wtfp,&secbuf[0],status,HEX);
  194.         break;
  195.       case '*': /* Enter ascii-modify mode */
  196.         edit_window(wtfp,&secbuf[0],status,ASC);
  197.     }
  198.     prevchar=inkey; /* update previous char for CSI sequence checks */
  199.   }
  200.   while (inkey!=3); /* loop until CTRL-C */
  201.   
  202.   close(rdfp); close(wtfp); exit(0); /* cleanup & exit */
  203. }
  204.  
  205. display_record(fp,secbuf,cursec,finsec,eof)
  206. int fp,cursec,finsec,eof;
  207. char secbuf[16][16];
  208.  
  209. {
  210.   int row,col,len,i;
  211.   char strbuf[100],*kludge;
  212.  
  213.   /* kludge maps 2-d array to 1-d so we can more easily
  214.      fill incomplete records w/dummy chars past EOF */
  215.  
  216.   kludge=&secbuf[0][0];
  217.   for (i=256;i>eof;--i) kludge[i-1]='#';
  218.  
  219.   /* EOL's included below to erase old values */
  220.   len=sprintf(&strbuf[0],"\x9bKCur rec : %d",cursec);
  221.   prstr(fp,62,1,&strbuf[0]);
  222.   len=sprintf(&strbuf[0],"\x9bKEnd rec : %d",finsec);
  223.   prstr(fp,62,2,&strbuf[0]);
  224.  
  225.   /* record display core routine : Due to the slowness of the
  226.      console file drivers, display is line buffered for speed. */
  227.  
  228.   for (row=0;row<=15;row++) {
  229.     locate(fp,6,row+1); i=0;
  230.     for (col=0;col<=15;col++) {
  231.       hexconv(&strbuf[i],secbuf[row][col]); i+=2;
  232.       if (((col+1)%4)==0) strbuf[i++]=' ';
  233.     }
  234.     strbuf[i++]=':'; strbuf[i++]=' ';
  235.     for (col=0;col<=15;col++) strbuf[i++]=valid_display(secbuf[row][col]);
  236.  
  237.     strbuf[i]='\0'; write(fp,&strbuf[0],strlen(&strbuf[0]));
  238.   }
  239. }
  240.  
  241. locate(fp,x,y) /* move cursor to x,y */
  242. int fp,x,y;
  243. {
  244.   char decimal[6];
  245.   int length;
  246.    
  247.   /* complete escape sequence for cursor pos is :
  248.      <CSI><row><;><col><H> where CSI is 9BH. */
  249.  
  250.   write(fp,"\x9b",1);
  251.   sprintf(&decimal[0],"%d",y); length=strlen(&decimal[0]);
  252. /* length=stci_d(&decimal[0],y,sizeof(decimal)); */
  253.   write(fp,&decimal[0],length);
  254.   write(fp,";",1);
  255.   sprintf(&decimal[0],"%d",x); length=strlen(&decimal[0]);
  256. /* length=stci_d(&decimal[0],x,sizeof(decimal)); */
  257.   write(fp,&decimal[0],length);
  258.   write(fp,"H",1);
  259. }
  260.       
  261. hexconv(result,byte) /* byte to 2 ASCII hex digits */
  262. unsigned char result[2],byte;
  263. {
  264.   result[0]=(byte>>4);
  265.   result[1]=(byte & 0xf);
  266.   if (result[0]<10) result[0]|=0x30; else result[0]+=55;
  267.   if (result[1]<10) result[1]|=0x30; else result[1]+=55;
  268. }
  269.  
  270. prstr(wtfp,posx,posy,string) /* "Print-At" routine */
  271. int wtfp,posx,posy;
  272. char *string;
  273. {
  274.   locate(wtfp,posx,posy);
  275.   write(wtfp,string,strlen(string));
  276. }
  277.  
  278. movecur(wtfp,secbuf,deltax,deltay,eof) /* move cursor & update display */
  279. int wtfp,deltax,deltay,eof;
  280. char secbuf[16][16];
  281.   char hexbuf[2];
  282.  
  283.   /* update ASCII side */
  284.   hexbuf[0]=valid_display(secbuf[phycury][phycurx]); hexbuf[1]='\0';
  285.   prstr(wtfp,phycurx+44,phycury+1,&hexbuf[0]);
  286.  
  287.   /* disallow cursor movement past EOF */
  288.   
  289.   if (fixpos(wtfp,eof,deltax,deltay)) return(0);
  290.  
  291.   hexconv(&hexbuf[0],(phycury*0x10)+phycurx); /* update HEX side */
  292.  
  293.   prstr(wtfp,62,9,"Loc : "); write(wtfp,&hexbuf[0],2);
  294.  
  295.   locate(wtfp,phycurx+44,phycury+1); /* update ASCII cursor */
  296.   write(wtfp,"*",1);
  297.   
  298.   locate(wtfp,posconv[phycurx],phycury+1); /* update HEX ("real") cursor */
  299. }
  300. edit_window(wtfp,secbuf,eof,hex) /* record edit routine */
  301. int wtfp,eof,hex;
  302. char secbuf[16][16];
  303. {
  304.   char ascii,lsb,msb,hexbuf[2];
  305.   int status=NULL,tempx;
  306.  
  307.   if (hex==HEX) prstr(wtfp,62,11,"\x9bKModify : HEX");
  308.   else prstr(wtfp,62,11,"\x9bKModify : ASCII");
  309.  
  310.   prstr(wtfp,62,12,"<ESC> to exit");
  311.  
  312.   do {
  313.     
  314.     locate(wtfp,posconv[phycurx],phycury+1); /* cursor over hex digits */
  315.     write(wtfp,"  ",2); /* erase previous entry */
  316.     locate(wtfp,posconv[phycurx],phycury+1); /* restore cursor */
  317.    
  318.     if (hex==HEX) { /* hex-modify : Actually, any invalid char exits */
  319.  
  320.       if ((msb=hexfetch(wtfp))==FALSE) { status=1; goto exit; }
  321.       write(wtfp,&msb,1); /* print msb */
  322.  
  323.       if ((lsb=hexfetch(wtfp))==FALSE) { status=1; goto exit; }
  324.       write(wtfp,&lsb,1); /* print lsb */
  325.   
  326.       if (msb>'9') msb-=55; else msb-='0'; /* hex to binary */
  327.       if (lsb>'9') lsb-=55; else lsb-='0';
  328.       secbuf[phycury][phycurx]=(msb<<4)+lsb; /* update buffer */
  329.     }
  330.     else { /* ASCII-modify */
  331.  
  332.       read(wtfp,&ascii,1); /* fetch ASCII char from user */
  333.       if (ascii==0x1b) { status=1; goto exit; }/* exit on <ESC> */
  334.       secbuf[phycury][phycurx]=ascii; /* update buffer */
  335.     }
  336. exit:
  337.     locate(wtfp,posconv[phycurx],phycury+1); /* restore cursor */
  338.     hexconv(&hexbuf[0],secbuf[phycury][phycurx]);
  339.     write(wtfp,&hexbuf[0],2); /* rewrite old value in case cancelled */
  340.  
  341.     movecur(wtfp,&secbuf[0],0,0,eof); /* update ASCII side */
  342.     if (status==1) break; /* don't move cursor if <ESC> */
  343.  
  344.     tempx=phycurx; /* save previous x-coord */
  345.     movecur(wtfp,&secbuf[0],1,0,eof); /* move to next digit */
  346.     if (tempx==phycurx) status=1; /* cancel modify if blocked */
  347.   }
  348.   while (status==NULL); /* edit until exit */
  349.  
  350.   prstr(wtfp,62,11,"\x9bK"); /* erase info msgs */
  351.   prstr(wtfp,62,12,"\x9bK");
  352.   locate(wtfp,posconv[phycurx],phycury+1); /* restore cursor B4 exit */
  353. }
  354.  
  355. hexfetch(wtfp) /* Fetch valid ascii HEX sequence from user */
  356. int wtfp;
  357. {
  358.    unsigned char nybble;
  359.  
  360.   for (;;) {
  361.     read(wtfp,&nybble,1);
  362.     if (nybble==0x1b) return(FALSE);
  363.     if (!isalnum(nybble)) continue;
  364.     nybble=toupper(nybble);
  365.     if (nybble>'F') continue;
  366.     return (int)nybble;
  367.   }
  368. }
  369.   
  370. fixpos(wtfp,eof,deltax,deltay) /* cursor bounds check routine */
  371. int wtfp,eof,deltax,deltay;
  372. {
  373.   int tempx,tempy;
  374.  
  375.   tempx=phycurx+deltax; tempy=phycury+deltay;
  376.  
  377.   if (tempx>15) { tempy++; tempx=0; } /* cursor screen-wrap code */
  378.   if (tempy>15) tempy=0;
  379.   if (tempx<0)  { tempx=15; tempy--; }
  380.   if (tempy<0)  tempy=15;
  381.   
  382.   if ((((tempy)*16) + (tempx)) > eof-1) { /* cleanup & exit if past EOF */
  383.     locate(wtfp,phycurx+44,phycury+1); 
  384.     write(wtfp,"*",1); /* redraw ASCII cursor */
  385.     locate(wtfp,posconv[phycurx],phycury+1); /* redraw HEX cursor */
  386.     DisplayBeep(NULL); /* Flash user so he wakes up */
  387.     return(TRUE); /* and exit */
  388.   }
  389.   phycurx=tempx; phycury=tempy; /* Otherwise, update global cursor */
  390.   return(FALSE);
  391. }
  392.  
  393. valid_display(byte) /* return filtered ASCII char */
  394. char byte;
  395.  
  396. /* Filter all CTRL & CSI chars which could mess things up */
  397. {
  398.   if ((byte>31) && (byte!=0x9b)) return(int)byte;
  399.   else return(int)'.';
  400. }
  401.